package com.ym.domain.common.util;

public class SnowflakeIdWorker {

    private static final long datacenterId = 1;    // 数据中心ID（0-31）
    private static final long machineId = 1;       // 机器ID（0-31）
    private static long sequence = 0L;         // 序列号
    private static long lastTimestamp = -1L;   // 上次生成时间

    private SnowflakeIdWorker() { }

    public static synchronized long nextId() {
        long timestamp = timeGen();

        // 处理时钟回拨
        if (timestamp < lastTimestamp) {
            throw new RuntimeException("时钟回拨异常");
        }

        if (timestamp == lastTimestamp) {
            sequence = (sequence + 1) & 0xFFF; // 12位序列号
            if (sequence == 0) {
                timestamp = tilNextMillis(lastTimestamp); // 等待下一毫秒
            }
        } else {
            sequence = 0L;
        }

        lastTimestamp = timestamp;

        return ((timestamp) << 22)        // 41位时间戳
                | (datacenterId << 17)    // 5位数据中心ID
                | (machineId << 12)       // 5位机器ID
                | sequence;               // 12位序列号
    }

    private static long tilNextMillis(long lastTimestamp) {
        long timestamp = timeGen();
        while (timestamp <= lastTimestamp) {
            timestamp = timeGen();
        }
        return timestamp;
    }

    private static long timeGen() {
        return System.currentTimeMillis();
    }
}
